/*
 * RecordedDatabaseMakerView.java
 */
package recordeddatabasemaker;

import Player.AudioPlayer;
import Player.GraphPainter;
import Player.PhraseInfo;
import Player.RecordedDatabase;
import Player.SelectedPhrase;
import Player.TextFile;
import Player.WavFile;
import Player.XmlMerger;
import java.awt.BorderLayout;
import java.awt.Component;
import java.awt.Dimension;
import java.io.File;
import org.jdesktop.application.Action;
import org.jdesktop.application.ResourceMap;
import org.jdesktop.application.SingleFrameApplication;
import org.jdesktop.application.FrameView;
import org.jdesktop.application.TaskMonitor;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.ByteArrayOutputStream;
import java.io.PrintStream;
import javax.swing.Timer;
import javax.swing.Icon;
import javax.swing.JDialog;
import javax.swing.JFileChooser;
import javax.swing.JFrame;
import javax.swing.JOptionPane;
import javax.swing.JSlider;
import javax.swing.JSpinner;
import javax.swing.filechooser.FileNameExtensionFilter;

/**
 * The application's main frame.
 */
public class RecordedDatabaseMakerView extends FrameView {

    public RecordedDatabaseMakerView(SingleFrameApplication app) {
        super(app);

        initComponents();

        recordedDatabase = new RecordedDatabase();
        needToSave = false;
        frameSlider.setMaximum(GraphPainter.BUFFER_SIZE - 1);

        // status bar initialization - message timeout, idle icon and busy animation, etc
        ResourceMap resourceMap = getResourceMap();
        int messageTimeout = resourceMap.getInteger("StatusBar.messageTimeout");
        messageTimer = new Timer(messageTimeout, new ActionListener() {

            public void actionPerformed(ActionEvent e) {
            }
        });
        messageTimer.setRepeats(false);
        int busyAnimationRate = resourceMap.getInteger("StatusBar.busyAnimationRate");
        for (int i = 0; i < busyIcons.length; i++) {
            busyIcons[i] = resourceMap.getIcon("StatusBar.busyIcons[" + i + "]");
        }
        busyIconTimer = new Timer(busyAnimationRate, new ActionListener() {

            public void actionPerformed(ActionEvent e) {
                busyIconIndex = (busyIconIndex + 1) % busyIcons.length;
            }
        });
        idleIcon = resourceMap.getIcon("StatusBar.idleIcon");

        // connecting action tasks to status bar via TaskMonitor
        TaskMonitor taskMonitor = new TaskMonitor(getApplication().getContext());
        taskMonitor.addPropertyChangeListener(new java.beans.PropertyChangeListener() {

            public void propertyChange(java.beans.PropertyChangeEvent evt) {
                String propertyName = evt.getPropertyName();
                if ("started".equals(propertyName)) {
                    if (!busyIconTimer.isRunning()) {
                        busyIconIndex = 0;
                        busyIconTimer.start();
                    }
                } else if ("done".equals(propertyName)) {
                    busyIconTimer.stop();
                } else if ("message".equals(propertyName)) {
                    String text = (String) (evt.getNewValue());
                    messageTimer.restart();
                } else if ("progress".equals(propertyName)) {
                    int value = (Integer) (evt.getNewValue());
                }
            }
        });
    }

    @Action
    public void showAboutBox() {
        if (aboutBox == null) {
            JFrame mainFrame = RecordedDatabaseMakerApp.getApplication().getMainFrame();
            aboutBox = new RecordedDatabaseMakerAboutBox(mainFrame);
            aboutBox.setLocationRelativeTo(mainFrame);
        }
        RecordedDatabaseMakerApp.getApplication().show(aboutBox);
    }

    /** This method is called from within the constructor to
     * initialize the form.
     * WARNING: Do NOT modify this code. The content of this method is
     * always regenerated by the Form Editor.
     */
    @SuppressWarnings("unchecked")
    // <editor-fold defaultstate="collapsed" desc="Generated Code">//GEN-BEGIN:initComponents
    private void initComponents() {

        mainPanel = new javax.swing.JPanel();
        graphPanel = new javax.swing.JPanel();
        frameSlider = new javax.swing.JSlider();
        playButton = new javax.swing.JButton();
        finishLabel = new javax.swing.JLabel();
        startLabel = new javax.swing.JLabel();
        startSpinner = new javax.swing.JSpinner();
        finishSpinner = new javax.swing.JSpinner();
        currentPhraseLabel = new javax.swing.JLabel();
        currentPhraseTextField = new javax.swing.JTextField();
        minusButton = new javax.swing.JButton();
        plusButton = new javax.swing.JButton();
        savePhraseButton = new javax.swing.JButton();
        savedPhraseScrollPane = new javax.swing.JScrollPane();
        savedPhraseTextArea = new javax.swing.JTextArea();
        textContentScrollPane = new javax.swing.JScrollPane();
        textContentArea = new javax.swing.JTextArea();
        delButton = new javax.swing.JButton();
        ymaxSlider = new javax.swing.JSlider();
        playRemainButton = new javax.swing.JButton();
        xmaxSlider = new javax.swing.JSlider();
        undoButton = new javax.swing.JButton();
        saveWaveButton = new javax.swing.JButton();
        menuBar = new javax.swing.JMenuBar();
        javax.swing.JMenu fileMenu = new javax.swing.JMenu();
        openAudioItem = new javax.swing.JMenuItem();
        openTextItem = new javax.swing.JMenuItem();
        newMenuItem = new javax.swing.JMenuItem();
        saveResultItem = new javax.swing.JMenuItem();
        mergeAllXmlItem = new javax.swing.JMenuItem();
        javax.swing.JMenuItem exitMenuItem = new javax.swing.JMenuItem();
        viewMenu = new javax.swing.JMenu();
        audioInfoMenuItem = new javax.swing.JMenuItem();
        javax.swing.JMenu helpMenu = new javax.swing.JMenu();
        javax.swing.JMenuItem aboutMenuItem = new javax.swing.JMenuItem();
        statusPanel = new javax.swing.JPanel();
        javax.swing.JSeparator statusPanelSeparator = new javax.swing.JSeparator();
        textFileLabel = new javax.swing.JLabel();
        audioFileLabel = new javax.swing.JLabel();

        mainPanel.setName("mainPanel"); // NOI18N
        mainPanel.setPreferredSize(new java.awt.Dimension(1024, 768));
        mainPanel.setSize(new java.awt.Dimension(1024, 768));

        org.jdesktop.application.ResourceMap resourceMap = org.jdesktop.application.Application.getInstance(recordeddatabasemaker.RecordedDatabaseMakerApp.class).getContext().getResourceMap(RecordedDatabaseMakerView.class);
        graphPanel.setBackground(resourceMap.getColor("graphPanel.background")); // NOI18N
        graphPanel.setBorder(javax.swing.BorderFactory.createEtchedBorder());
        graphPanel.setName("graphPanel"); // NOI18N

        org.jdesktop.layout.GroupLayout graphPanelLayout = new org.jdesktop.layout.GroupLayout(graphPanel);
        graphPanel.setLayout(graphPanelLayout);
        graphPanelLayout.setHorizontalGroup(
            graphPanelLayout.createParallelGroup(org.jdesktop.layout.GroupLayout.LEADING)
            .add(0, 1430, Short.MAX_VALUE)
        );
        graphPanelLayout.setVerticalGroup(
            graphPanelLayout.createParallelGroup(org.jdesktop.layout.GroupLayout.LEADING)
            .add(0, 384, Short.MAX_VALUE)
        );

        frameSlider.setMajorTickSpacing(2000);
        frameSlider.setMaximum(10000);
        frameSlider.setMinorTickSpacing(1);
        frameSlider.setPaintLabels(true);
        frameSlider.setSnapToTicks(true);
        frameSlider.setValue(0);
        frameSlider.setEnabled(false);
        frameSlider.setName("frameSlider"); // NOI18N
        frameSlider.addChangeListener(new javax.swing.event.ChangeListener() {
            public void stateChanged(javax.swing.event.ChangeEvent evt) {
                frameSliderStateChanged(evt);
            }
        });

        playButton.setText(resourceMap.getString("playButton.text")); // NOI18N
        playButton.setEnabled(false);
        playButton.setName("playButton"); // NOI18N
        playButton.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                playButtonActionPerformed(evt);
            }
        });

        finishLabel.setText(resourceMap.getString("finishLabel.text")); // NOI18N
        finishLabel.setName("finishLabel"); // NOI18N

        startLabel.setText(resourceMap.getString("startLabel.text")); // NOI18N
        startLabel.setName("startLabel"); // NOI18N

        startSpinner.setEnabled(false);
        startSpinner.setName("startSpinner"); // NOI18N
        startSpinner.addChangeListener(new javax.swing.event.ChangeListener() {
            public void stateChanged(javax.swing.event.ChangeEvent evt) {
                startSpinnerStateChanged(evt);
            }
        });

        finishSpinner.setEnabled(false);
        finishSpinner.setName("finishSpinner"); // NOI18N
        finishSpinner.addChangeListener(new javax.swing.event.ChangeListener() {
            public void stateChanged(javax.swing.event.ChangeEvent evt) {
                finishSpinnerStateChanged(evt);
            }
        });

        currentPhraseLabel.setText(resourceMap.getString("currentPhraseLabel.text")); // NOI18N
        currentPhraseLabel.setName("currentPhraseLabel"); // NOI18N

        currentPhraseTextField.setFont(resourceMap.getFont("currentPhraseTextField.font")); // NOI18N
        currentPhraseTextField.setForeground(resourceMap.getColor("currentPhraseTextField.foreground")); // NOI18N
        currentPhraseTextField.setText(resourceMap.getString("currentPhraseTextField.text")); // NOI18N
        currentPhraseTextField.setName("currentPhraseTextField"); // NOI18N

        minusButton.setText(resourceMap.getString("minusButton.text")); // NOI18N
        minusButton.setEnabled(false);
        minusButton.setName("minusButton"); // NOI18N
        minusButton.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                minusButtonActionPerformed(evt);
            }
        });

        plusButton.setText(resourceMap.getString("plusButton.text")); // NOI18N
        plusButton.setEnabled(false);
        plusButton.setName("plusButton"); // NOI18N
        plusButton.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                plusButtonActionPerformed(evt);
            }
        });

        savePhraseButton.setText(resourceMap.getString("savePhraseButton.text")); // NOI18N
        savePhraseButton.setEnabled(false);
        savePhraseButton.setName("savePhraseButton"); // NOI18N
        savePhraseButton.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                savePhraseButtonActionPerformed(evt);
            }
        });

        savedPhraseScrollPane.setName("savedPhraseScrollPane"); // NOI18N

        savedPhraseTextArea.setColumns(20);
        savedPhraseTextArea.setEditable(false);
        savedPhraseTextArea.setFont(resourceMap.getFont("savedPhraseTextArea.font")); // NOI18N
        savedPhraseTextArea.setRows(5);
        savedPhraseTextArea.setName("savedPhraseTextArea"); // NOI18N
        savedPhraseScrollPane.setViewportView(savedPhraseTextArea);

        textContentScrollPane.setName("textContentScrollPane"); // NOI18N

        textContentArea.setColumns(20);
        textContentArea.setEditable(false);
        textContentArea.setRows(5);
        textContentArea.setName("textContentArea"); // NOI18N
        textContentScrollPane.setViewportView(textContentArea);

        delButton.setText(resourceMap.getString("delButton.text")); // NOI18N
        delButton.setEnabled(false);
        delButton.setName("delButton"); // NOI18N
        delButton.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                delButtonActionPerformed(evt);
            }
        });

        ymaxSlider.setMajorTickSpacing(1);
        ymaxSlider.setMaximum(9);
        ymaxSlider.setOrientation(javax.swing.JSlider.VERTICAL);
        ymaxSlider.setPaintLabels(true);
        ymaxSlider.setPaintTicks(true);
        ymaxSlider.setSnapToTicks(true);
        ymaxSlider.setValue(5);
        ymaxSlider.setEnabled(false);
        ymaxSlider.setName("ymaxSlider"); // NOI18N
        ymaxSlider.addChangeListener(new javax.swing.event.ChangeListener() {
            public void stateChanged(javax.swing.event.ChangeEvent evt) {
                ymaxSliderStateChanged(evt);
            }
        });

        playRemainButton.setText(resourceMap.getString("playRemainButton.text")); // NOI18N
        playRemainButton.setEnabled(false);
        playRemainButton.setName("playRemainButton"); // NOI18N
        playRemainButton.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                playRemainButtonActionPerformed(evt);
            }
        });

        xmaxSlider.setMaximum(4);
        xmaxSlider.setMinimum(-1);
        xmaxSlider.setMinorTickSpacing(1);
        xmaxSlider.setPaintLabels(true);
        xmaxSlider.setPaintTicks(true);
        xmaxSlider.setSnapToTicks(true);
        xmaxSlider.setValue(2);
        xmaxSlider.setEnabled(false);
        xmaxSlider.setName("xmaxSlider"); // NOI18N
        xmaxSlider.addChangeListener(new javax.swing.event.ChangeListener() {
            public void stateChanged(javax.swing.event.ChangeEvent evt) {
                xmaxSliderStateChanged(evt);
            }
        });

        undoButton.setText(resourceMap.getString("undoButton.text")); // NOI18N
        undoButton.setEnabled(false);
        undoButton.setName("undoButton"); // NOI18N
        undoButton.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                undoButtonActionPerformed(evt);
            }
        });

        saveWaveButton.setText(resourceMap.getString("saveWaveButton.text")); // NOI18N
        saveWaveButton.setEnabled(false);
        saveWaveButton.setName("saveWaveButton"); // NOI18N
        saveWaveButton.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                saveWaveButtonActionPerformed(evt);
            }
        });

        org.jdesktop.layout.GroupLayout mainPanelLayout = new org.jdesktop.layout.GroupLayout(mainPanel);
        mainPanel.setLayout(mainPanelLayout);
        mainPanelLayout.setHorizontalGroup(
            mainPanelLayout.createParallelGroup(org.jdesktop.layout.GroupLayout.LEADING)
            .add(mainPanelLayout.createSequentialGroup()
                .addContainerGap()
                .add(mainPanelLayout.createParallelGroup(org.jdesktop.layout.GroupLayout.LEADING)
                    .add(mainPanelLayout.createSequentialGroup()
                        .add(graphPanel, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
                        .addContainerGap())
                    .add(mainPanelLayout.createSequentialGroup()
                        .add(mainPanelLayout.createParallelGroup(org.jdesktop.layout.GroupLayout.TRAILING)
                            .add(org.jdesktop.layout.GroupLayout.LEADING, mainPanelLayout.createSequentialGroup()
                                .add(mainPanelLayout.createParallelGroup(org.jdesktop.layout.GroupLayout.LEADING)
                                    .add(mainPanelLayout.createSequentialGroup()
                                        .add(mainPanelLayout.createParallelGroup(org.jdesktop.layout.GroupLayout.TRAILING, false)
                                            .add(playRemainButton, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
                                            .add(playButton, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, 151, Short.MAX_VALUE))
                                        .add(18, 18, 18)
                                        .add(savePhraseButton)
                                        .add(18, 18, 18)
                                        .add(mainPanelLayout.createParallelGroup(org.jdesktop.layout.GroupLayout.TRAILING)
                                            .add(saveWaveButton)
                                            .add(currentPhraseLabel, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE, 100, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE))
                                        .addPreferredGap(org.jdesktop.layout.LayoutStyle.UNRELATED)
                                        .add(mainPanelLayout.createParallelGroup(org.jdesktop.layout.GroupLayout.LEADING)
                                            .add(mainPanelLayout.createSequentialGroup()
                                                .add(minusButton)
                                                .addPreferredGap(org.jdesktop.layout.LayoutStyle.RELATED)
                                                .add(plusButton)
                                                .addPreferredGap(org.jdesktop.layout.LayoutStyle.RELATED)
                                                .add(delButton))
                                            .add(currentPhraseTextField, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE, 238, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE))
                                        .add(mainPanelLayout.createParallelGroup(org.jdesktop.layout.GroupLayout.LEADING)
                                            .add(org.jdesktop.layout.GroupLayout.TRAILING, mainPanelLayout.createSequentialGroup()
                                                .addPreferredGap(org.jdesktop.layout.LayoutStyle.RELATED)
                                                .add(startLabel)
                                                .addPreferredGap(org.jdesktop.layout.LayoutStyle.UNRELATED))
                                            .add(mainPanelLayout.createSequentialGroup()
                                                .add(18, 18, 18)
                                                .add(finishLabel)
                                                .add(11, 11, 11)))
                                        .add(mainPanelLayout.createParallelGroup(org.jdesktop.layout.GroupLayout.TRAILING, false)
                                            .add(org.jdesktop.layout.GroupLayout.LEADING, finishSpinner)
                                            .add(org.jdesktop.layout.GroupLayout.LEADING, startSpinner, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, 152, Short.MAX_VALUE)))
                                    .add(mainPanelLayout.createSequentialGroup()
                                        .add(textContentScrollPane, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE, 745, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE)
                                        .addPreferredGap(org.jdesktop.layout.LayoutStyle.UNRELATED)
                                        .add(mainPanelLayout.createParallelGroup(org.jdesktop.layout.GroupLayout.LEADING)
                                            .add(undoButton)
                                            .add(xmaxSlider, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE, 112, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE))
                                        .addPreferredGap(org.jdesktop.layout.LayoutStyle.RELATED)
                                        .add(ymaxSlider, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE)))
                                .addPreferredGap(org.jdesktop.layout.LayoutStyle.RELATED)
                                .add(savedPhraseScrollPane, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, 499, Short.MAX_VALUE))
                            .add(org.jdesktop.layout.GroupLayout.LEADING, frameSlider, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, 1434, Short.MAX_VALUE))
                        .add(20, 20, 20))))
        );
        mainPanelLayout.setVerticalGroup(
            mainPanelLayout.createParallelGroup(org.jdesktop.layout.GroupLayout.LEADING)
            .add(org.jdesktop.layout.GroupLayout.TRAILING, mainPanelLayout.createSequentialGroup()
                .addContainerGap()
                .add(mainPanelLayout.createParallelGroup(org.jdesktop.layout.GroupLayout.LEADING)
                    .add(mainPanelLayout.createSequentialGroup()
                        .add(mainPanelLayout.createParallelGroup(org.jdesktop.layout.GroupLayout.LEADING)
                            .add(org.jdesktop.layout.GroupLayout.TRAILING, ymaxSlider, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, 183, Short.MAX_VALUE)
                            .add(org.jdesktop.layout.GroupLayout.TRAILING, textContentScrollPane, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, 183, Short.MAX_VALUE)
                            .add(org.jdesktop.layout.GroupLayout.TRAILING, mainPanelLayout.createSequentialGroup()
                                .add(xmaxSlider, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE)
                                .addPreferredGap(org.jdesktop.layout.LayoutStyle.RELATED, 116, Short.MAX_VALUE)
                                .add(undoButton)))
                        .addPreferredGap(org.jdesktop.layout.LayoutStyle.UNRELATED)
                        .add(mainPanelLayout.createParallelGroup(org.jdesktop.layout.GroupLayout.LEADING)
                            .add(mainPanelLayout.createSequentialGroup()
                                .add(startSpinner, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE, 36, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE)
                                .addPreferredGap(org.jdesktop.layout.LayoutStyle.RELATED)
                                .add(finishSpinner, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE, 34, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE))
                            .add(mainPanelLayout.createParallelGroup(org.jdesktop.layout.GroupLayout.LEADING, false)
                                .add(org.jdesktop.layout.GroupLayout.TRAILING, mainPanelLayout.createSequentialGroup()
                                    .add(mainPanelLayout.createParallelGroup(org.jdesktop.layout.GroupLayout.TRAILING)
                                        .add(org.jdesktop.layout.GroupLayout.LEADING, savePhraseButton, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, 78, Short.MAX_VALUE)
                                        .add(mainPanelLayout.createSequentialGroup()
                                            .add(playRemainButton, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, 36, Short.MAX_VALUE)
                                            .addPreferredGap(org.jdesktop.layout.LayoutStyle.UNRELATED)
                                            .add(playButton, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE, 42, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE)))
                                    .add(8, 8, 8))
                                .add(mainPanelLayout.createSequentialGroup()
                                    .add(mainPanelLayout.createParallelGroup(org.jdesktop.layout.GroupLayout.BASELINE)
                                        .add(currentPhraseTextField, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE, 37, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE)
                                        .add(currentPhraseLabel)
                                        .add(startLabel))
                                    .add(mainPanelLayout.createParallelGroup(org.jdesktop.layout.GroupLayout.LEADING)
                                        .add(mainPanelLayout.createSequentialGroup()
                                            .add(10, 10, 10)
                                            .add(mainPanelLayout.createParallelGroup(org.jdesktop.layout.GroupLayout.BASELINE)
                                                .add(minusButton, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE, 34, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE)
                                                .add(plusButton, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE, 33, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE)
                                                .add(delButton, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE, 33, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE)
                                                .add(saveWaveButton, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE, 33, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE)))
                                        .add(mainPanelLayout.createSequentialGroup()
                                            .addPreferredGap(org.jdesktop.layout.LayoutStyle.UNRELATED)
                                            .add(finishLabel)))))))
                    .add(savedPhraseScrollPane, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, 283, Short.MAX_VALUE))
                .addPreferredGap(org.jdesktop.layout.LayoutStyle.RELATED)
                .add(frameSlider, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE)
                .addPreferredGap(org.jdesktop.layout.LayoutStyle.RELATED)
                .add(graphPanel, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE))
        );

        menuBar.setName("menuBar"); // NOI18N

        fileMenu.setText(resourceMap.getString("fileMenu.text")); // NOI18N
        fileMenu.setName("fileMenu"); // NOI18N

        openAudioItem.setText(resourceMap.getString("openAudioItem.text")); // NOI18N
        openAudioItem.setName("openAudioItem"); // NOI18N
        openAudioItem.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                openAudioItemActionPerformed(evt);
            }
        });
        fileMenu.add(openAudioItem);

        openTextItem.setText(resourceMap.getString("openTextItem.text")); // NOI18N
        openTextItem.setName("openTextItem"); // NOI18N
        openTextItem.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                openTextItemActionPerformed(evt);
            }
        });
        fileMenu.add(openTextItem);

        newMenuItem.setText(resourceMap.getString("newMenuItem.text")); // NOI18N
        newMenuItem.setName("newMenuItem"); // NOI18N
        newMenuItem.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                newMenuItemActionPerformed(evt);
            }
        });
        fileMenu.add(newMenuItem);

        saveResultItem.setText(resourceMap.getString("saveResultItem.text")); // NOI18N
        saveResultItem.setName("saveResultItem"); // NOI18N
        saveResultItem.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                saveResultItemActionPerformed(evt);
            }
        });
        fileMenu.add(saveResultItem);

        mergeAllXmlItem.setText(resourceMap.getString("mergeAllXmlItem.text")); // NOI18N
        mergeAllXmlItem.setName("mergeAllXmlItem"); // NOI18N
        mergeAllXmlItem.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                mergeAllXmlItemActionPerformed(evt);
            }
        });
        fileMenu.add(mergeAllXmlItem);

        javax.swing.ActionMap actionMap = org.jdesktop.application.Application.getInstance(recordeddatabasemaker.RecordedDatabaseMakerApp.class).getContext().getActionMap(RecordedDatabaseMakerView.class, this);
        exitMenuItem.setAction(actionMap.get("quit")); // NOI18N
        exitMenuItem.setName("exitMenuItem"); // NOI18N
        exitMenuItem.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                exitMenuItemActionPerformed(evt);
            }
        });
        fileMenu.add(exitMenuItem);

        menuBar.add(fileMenu);

        viewMenu.setText(resourceMap.getString("viewMenu.text")); // NOI18N
        viewMenu.setName("viewMenu"); // NOI18N

        audioInfoMenuItem.setText(resourceMap.getString("audioInfoMenuItem.text")); // NOI18N
        audioInfoMenuItem.setEnabled(false);
        audioInfoMenuItem.setName("audioInfoMenuItem"); // NOI18N
        audioInfoMenuItem.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                audioInfoMenuItemActionPerformed(evt);
            }
        });
        viewMenu.add(audioInfoMenuItem);

        menuBar.add(viewMenu);

        helpMenu.setText(resourceMap.getString("helpMenu.text")); // NOI18N
        helpMenu.setName("helpMenu"); // NOI18N

        aboutMenuItem.setAction(actionMap.get("showAboutBox")); // NOI18N
        aboutMenuItem.setName("aboutMenuItem"); // NOI18N
        helpMenu.add(aboutMenuItem);

        menuBar.add(helpMenu);

        statusPanel.setName("statusPanel"); // NOI18N

        statusPanelSeparator.setName("statusPanelSeparator"); // NOI18N

        textFileLabel.setText(resourceMap.getString("textFileLabel.text")); // NOI18N
        textFileLabel.setName("textFileLabel"); // NOI18N

        audioFileLabel.setText(resourceMap.getString("audioFileLabel.text")); // NOI18N
        audioFileLabel.setName("audioFileLabel"); // NOI18N

        org.jdesktop.layout.GroupLayout statusPanelLayout = new org.jdesktop.layout.GroupLayout(statusPanel);
        statusPanel.setLayout(statusPanelLayout);
        statusPanelLayout.setHorizontalGroup(
            statusPanelLayout.createParallelGroup(org.jdesktop.layout.GroupLayout.LEADING)
            .add(statusPanelLayout.createSequentialGroup()
                .add(statusPanelLayout.createParallelGroup(org.jdesktop.layout.GroupLayout.LEADING)
                    .add(statusPanelLayout.createSequentialGroup()
                        .add(28, 28, 28)
                        .add(statusPanelLayout.createParallelGroup(org.jdesktop.layout.GroupLayout.LEADING)
                            .add(textFileLabel)
                            .add(audioFileLabel)))
                    .add(statusPanelSeparator, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE, 1439, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE))
                .addContainerGap(35, Short.MAX_VALUE))
        );
        statusPanelLayout.setVerticalGroup(
            statusPanelLayout.createParallelGroup(org.jdesktop.layout.GroupLayout.LEADING)
            .add(statusPanelLayout.createSequentialGroup()
                .add(statusPanelSeparator, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE, 4, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE)
                .addPreferredGap(org.jdesktop.layout.LayoutStyle.RELATED)
                .add(textFileLabel)
                .addPreferredGap(org.jdesktop.layout.LayoutStyle.RELATED, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
                .add(audioFileLabel)
                .addContainerGap())
        );

        setComponent(mainPanel);
        setMenuBar(menuBar);
        setStatusBar(statusPanel);
    }// </editor-fold>//GEN-END:initComponents

    private void openAudioItemActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_openAudioItemActionPerformed
        JFileChooser fileChooser = new JFileChooser();
        fileChooser.setMultiSelectionEnabled(false);
        FileNameExtensionFilter filter = new FileNameExtensionFilter("Wave files (*.wav)", "wav");
        fileChooser.setFileFilter(filter);
        if (lastDirectory != null) {
            fileChooser.setCurrentDirectory(lastDirectory);
        }

        if (fileChooser.showOpenDialog(mainPanel) == JFileChooser.APPROVE_OPTION) {
            try {
                lastDirectory = fileChooser.getCurrentDirectory();

                File selectedFile = fileChooser.getSelectedFile();
                currentAudioFile = selectedFile;

                audioFileLabel.setText("Audio File: " + selectedFile.getAbsolutePath());
                player = new AudioPlayer(selectedFile);

                graphPainter = new GraphPainter(selectedFile, graphPanel.getWidth(), graphPanel.getHeight());
                graphPanel.add(graphPainter);
                graphPainter.refresh();
                graphPainter.changeMaxScore(ymaxSlider.getValue() - DEFAULT_LEVEL);

                selectedPhrase = new SelectedPhrase(new Dimension(GraphPainter.BORDER_GAP, graphPanel.getHeight()));
                graphPainter.setLayout(new BorderLayout());
                graphPainter.add(selectedPhrase, BorderLayout.WEST);

                startSpinner.setValue(0);
                finishSpinner.setValue(0);
                finishSpinner.setEnabled(true);
                frameSlider.setEnabled(true);
                xmaxSlider.setEnabled(true);
                ymaxSlider.setEnabled(true);
                playButton.setEnabled(true);
                playRemainButton.setEnabled(true);
                openAudioItem.setEnabled(false);

                ByteArrayOutputStream baos = new ByteArrayOutputStream();
                PrintStream ps = new PrintStream(baos);
                graphPainter.getWavFile().display(ps);
                audioInfo = baos.toString();
                audioInfoMenuItem.setEnabled(true);
            } catch (Exception ex) {
                JOptionPane.showMessageDialog(mainPanel, ex.getMessage());
                ex.printStackTrace();
            }
        }
    }//GEN-LAST:event_openAudioItemActionPerformed

    private void frameSliderStateChanged(javax.swing.event.ChangeEvent evt) {//GEN-FIRST:event_frameSliderStateChanged
        JSlider slider = (JSlider) evt.getSource();
        updateSavePhraseButton();

        int value = slider.getValue();
        finishSpinner.setValue(value);

        if (graphPainter == null || selectedPhrase == null) {
            return;
        }

        if (value - slider.getMinimum() >= graphPainter.getRemainFrames()) {
            value = slider.getMinimum() + graphPainter.getRemainFrames() - 1;
            slider.setValue(value);
        }

        int width = graphPainter.getX(value - slider.getMinimum());
        if (width != selectedPhrase.getWidth()) {
            selectedPhrase.setWidth(width);
        }
    }//GEN-LAST:event_frameSliderStateChanged

    private void playButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_playButtonActionPerformed
        try {
            player.play(frameSlider.getMinimum(), frameSlider.getValue());
        } catch (Exception ex) {
            JOptionPane.showMessageDialog(mainPanel, ex.getMessage());
            ex.printStackTrace();
        }
    }//GEN-LAST:event_playButtonActionPerformed

    private String nextSyllable() {
        String s = textContentArea.getText() + " ";
        int index = s.indexOf(' ');
        if (index == -1) {
            return "";
        }
        textContentArea.setText(s.substring(index + 1).trim());
        textContentArea.setCaretPosition(0);
        return s.substring(0, index).trim();
    }

    private void openTextItemActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_openTextItemActionPerformed
        JFileChooser fileChooser = new JFileChooser();
        fileChooser.setMultiSelectionEnabled(false);
        FileNameExtensionFilter filter = new FileNameExtensionFilter("Text files (*.txt)", "txt");
        fileChooser.setFileFilter(filter);
        if (lastDirectory != null) {
            fileChooser.setCurrentDirectory(lastDirectory);
        }

        if (fileChooser.showOpenDialog(mainPanel) == JFileChooser.APPROVE_OPTION) {
            try {
                lastDirectory = fileChooser.getCurrentDirectory();
                File selectedFile = fileChooser.getSelectedFile();
                textFileLabel.setText("Text File: " + selectedFile.getAbsolutePath());
                currentTextFile = selectedFile;

                TextFile textFile = new TextFile(selectedFile);
                textFile.readAll();
                textContentArea.setText(textFile.getContent());
                textContentArea.setCaretPosition(0);
                textContentArea.setEditable(true);
                textContentArea.setEnabled(true);
                textContentArea.setLineWrap(true);
                textContentArea.setWrapStyleWord(true);

                String syllable = nextSyllable();
                if (syllable.length() > 0) {
                    currentPhraseTextField.setText(syllable);
                    setNumberCurrentSyllables(1);
                } else {
                    currentPhraseTextField.setText("");
                    setNumberCurrentSyllables(0);
                }

                updateSavePhraseButton();
                openTextItem.setEnabled(false);
            } catch (Exception ex) {
                JOptionPane.showMessageDialog(mainPanel, ex.getMessage());
                ex.printStackTrace();
            }
        }
    }//GEN-LAST:event_openTextItemActionPerformed

    private void finishSpinnerStateChanged(javax.swing.event.ChangeEvent evt) {//GEN-FIRST:event_finishSpinnerStateChanged
        JSpinner spinner = (JSpinner) evt.getSource();
        int currentValue = (Integer) spinner.getValue();
        if (currentValue > frameSlider.getMaximum()) {
            spinner.setValue(frameSlider.getMaximum());
        } else if (currentValue < frameSlider.getMinimum()) {
            spinner.setValue(frameSlider.getMinimum());
        } else {
            frameSlider.setValue(currentValue);
        }
    }//GEN-LAST:event_finishSpinnerStateChanged

    private void plusButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_plusButtonActionPerformed
        if (numberCurrentSyllables >= 5) {
            return;
        }
        String syllable = nextSyllable();
        if (syllable.length() > 0) {
            currentPhraseTextField.setText((currentPhraseTextField.getText() + " " + syllable).trim());
            setNumberCurrentSyllables(numberCurrentSyllables + 1);
            updateSavePhraseButton();
        }
    }//GEN-LAST:event_plusButtonActionPerformed

    private String lastSyllable() {
        String s = currentPhraseTextField.getText();
        if (numberCurrentSyllables == 1) {
            currentPhraseTextField.setText("");
            return s.trim();
        }
        int index = s.lastIndexOf(' ');
        if (index == -1) {
            return "";
        }
        currentPhraseTextField.setText(s.substring(0, index).trim());
        return s.substring(index + 1).trim();
    }

    private void minusButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_minusButtonActionPerformed
        if (numberCurrentSyllables <= 0) {
            return;
        }
        String syllable = lastSyllable();
        if (syllable.length() > 0) {
            textContentArea.setText((syllable + " " + textContentArea.getText()).trim());
            textContentArea.setCaretPosition(0);
            setNumberCurrentSyllables(numberCurrentSyllables - 1);
            updateSavePhraseButton();
        }
    }//GEN-LAST:event_minusButtonActionPerformed

    private void setNumberCurrentSyllables(int number) {
        numberCurrentSyllables = number;
        if (number <= 0) {
            minusButton.setEnabled(false);
        } else {
            minusButton.setEnabled(true);
        }
        if (number >= 5) {
            plusButton.setEnabled(false);
        } else {
            plusButton.setEnabled(true);
        }
    }

    void doCutPhrase(String phraseContent) {
        String fileName = currentAudioFile.getName();
        int startFrame = (Integer) startSpinner.getValue();
        int finishFrame = (Integer) finishSpinner.getValue();
        recordedDatabase.addPhrase(new PhraseInfo(phraseContent, fileName, startFrame, finishFrame));

        String currentPhrase = "[" + phraseContent + "] - [" + startFrame + ".." + finishFrame + "]";
        if (savedPhraseTextArea.getText().length() > 0) {
            savedPhraseTextArea.setText(savedPhraseTextArea.getText() + "\n" + currentPhrase);
        } else {
            savedPhraseTextArea.setText(currentPhrase);
        }

        try {
            graphPainter.moveGraphLeft(finishFrame - startFrame + 1);
            startSpinner.setValue(finishFrame + 1);
            finishSpinner.setValue(finishFrame + 1);
        } catch (Exception ex) {
            JOptionPane.showMessageDialog(mainPanel, ex.getMessage());
            ex.printStackTrace();
        }
    }

    private void updateCurrentPhrase() {
        String syllable = nextSyllable();
        if (syllable.length() > 0) {
            currentPhraseTextField.setText(syllable);
            setNumberCurrentSyllables(1);
        } else {
            currentPhraseTextField.setText("");
            setNumberCurrentSyllables(0);
        }
    }

    private void savePhraseButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_savePhraseButtonActionPerformed
        needToSave = true;
        doCutPhrase(currentPhraseTextField.getText());
        updateCurrentPhrase();
        undoButton.setEnabled(true);
    }//GEN-LAST:event_savePhraseButtonActionPerformed

    void updateSavePhraseButton() {
        if (frameSlider.getValue() > frameSlider.getMinimum()) {
            delButton.setEnabled(true);
            saveWaveButton.setEnabled(true);
        } else {
            delButton.setEnabled(false);
            saveWaveButton.setEnabled(false);
        }
        if (numberCurrentSyllables > 0 && frameSlider.getValue() > frameSlider.getMinimum()) {
            savePhraseButton.setEnabled(true);
        } else {
            savePhraseButton.setEnabled(false);
        }
    }

    private void startSpinnerStateChanged(javax.swing.event.ChangeEvent evt) {//GEN-FIRST:event_startSpinnerStateChanged
        int value = (Integer) ((JSpinner) evt.getSource()).getValue();
        frameSlider.setMinimum(value);
        if (graphPainter != null) {
            frameSlider.setMaximum(value + graphPainter.getCurrentOxLen());
        } else {
            frameSlider.setMaximum(value + GraphPainter.BUFFER_SIZE - 1);
        }
        frameSlider.setValue(value);
    }//GEN-LAST:event_startSpinnerStateChanged

    private int doSaveResult() {
        JFileChooser fileChooser = new JFileChooser();
        fileChooser.setMultiSelectionEnabled(false);
        FileNameExtensionFilter filter = new FileNameExtensionFilter("Xml files (*.xml)", "xml");
        fileChooser.setFileFilter(filter);

        if (lastDirectory != null) {
            fileChooser.setCurrentDirectory(lastDirectory);
        }

        int ret = fileChooser.showSaveDialog(mainPanel);
        if (ret == JFileChooser.APPROVE_OPTION) {
            lastDirectory = fileChooser.getCurrentDirectory();
            String path = fileChooser.getSelectedFile().getAbsolutePath();
            if (!path.endsWith(".xml")) {
                path = path + ".xml";
            }
            File selectedFile = new File(path);
            try {
                recordedDatabase.writeToXmlFile(selectedFile);
                needToSave = false;
            } catch (Exception ex) {
                JOptionPane.showMessageDialog(mainPanel, ex.getMessage());
                ex.printStackTrace();
            }
        }
        return ret;
    }

    private void saveResultItemActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_saveResultItemActionPerformed
        doSaveResult();
    }//GEN-LAST:event_saveResultItemActionPerformed

    private void ymaxSliderStateChanged(javax.swing.event.ChangeEvent evt) {//GEN-FIRST:event_ymaxSliderStateChanged
        JSlider slider = (JSlider) (evt.getSource());
        int level = slider.getValue() - DEFAULT_LEVEL;
        if (graphPainter != null) {
            graphPainter.changeMaxScore(level);
        }
    }//GEN-LAST:event_ymaxSliderStateChanged

    private void removeCurrentGraph() {
        if (graphPainter != null) {
            Component[] components = graphPanel.getComponents();
            for (int i = 0; i < components.length; ++i) {
                if (components[i] == graphPainter) {
                    graphPanel.remove(graphPainter);
                    graphPainter = null;
                    graphPanel.revalidate();
                    graphPanel.repaint();
                }
            }
        }
    }

    private void initialState() {
        removeCurrentGraph();
        openAudioItem.setEnabled(true);
        openTextItem.setEnabled(true);
        saveResultItem.setEnabled(true);

        textContentArea.setText("");
        textContentArea.setEditable(false);

        savedPhraseTextArea.setText("");
        savedPhraseTextArea.setEditable(false);

        frameSlider.setMinimum(0);
        frameSlider.setMaximum(GraphPainter.BUFFER_SIZE - 1);
        frameSlider.setValue(0);
        frameSlider.setEnabled(false);

        startSpinner.setValue(0);
        startSpinner.setEnabled(false);
        finishSpinner.setValue(0);
        finishSpinner.setEnabled(false);

        playButton.setEnabled(false);
        playRemainButton.setEnabled(false);
        delButton.setEnabled(false);
        plusButton.setEnabled(false);
        minusButton.setEnabled(false);
        savePhraseButton.setEnabled(false);
        currentPhraseTextField.setText("");
        currentPhraseTextField.setEnabled(true);
        currentPhraseTextField.setEditable(true);

        ymaxSlider.setEnabled(false);
        ymaxSlider.setValue(5);

        textFileLabel.setText("Text File:");
        audioFileLabel.setText("Audio File:");

        if (recordedDatabase != null) {
            recordedDatabase.clear();
        } else {
            recordedDatabase = new RecordedDatabase();
        }
        player = null;
        numberCurrentSyllables = 0;
        currentAudioFile = null;
        currentTextFile = null;
        selectedPhrase = null;
        needToSave = false;
        audioInfo = "";
        audioInfoMenuItem.setEnabled(false);
    }

    private void newMenuItemActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_newMenuItemActionPerformed
        if (needToSave) {
            int chose = JOptionPane.showConfirmDialog(mainPanel, "Your working result is not saved. Do you want to save current working result?");
            if (chose == JOptionPane.CANCEL_OPTION) {
                return;
            }
            if (chose == JOptionPane.YES_OPTION) {
                int ret = doSaveResult();
                if (ret != JFileChooser.APPROVE_OPTION) {
                    return;
                }
            }
        }
        initialState();
    }//GEN-LAST:event_newMenuItemActionPerformed

    private void delButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_delButtonActionPerformed
        needToSave = true;
        String phraseContent = currentPhraseTextField.getText();
        if (RecordedDatabase.isEndPhrase(phraseContent) || RecordedDatabase.isEndSentence(phraseContent)) {
            doCutPhrase(phraseContent);
            updateCurrentPhrase();
        } else {
            doCutPhrase("SIL");
        }
        undoButton.setEnabled(true);
    }//GEN-LAST:event_delButtonActionPerformed

    private void playRemainButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_playRemainButtonActionPerformed
        try {
            player.play(frameSlider.getValue(), frameSlider.getMaximum());
        } catch (Exception ex) {
            JOptionPane.showMessageDialog(mainPanel, ex.getMessage());
            ex.printStackTrace();
        }

    }//GEN-LAST:event_playRemainButtonActionPerformed

    private void exitMenuItemActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_exitMenuItemActionPerformed
        if (needToSave) {
            int chose = JOptionPane.showConfirmDialog(mainPanel, "Your working result is not saved. Do you want to save current working result?");
            if (chose == JOptionPane.YES_OPTION) {
                doSaveResult();
            }
        }
    }//GEN-LAST:event_exitMenuItemActionPerformed

    private void xmaxSliderStateChanged(javax.swing.event.ChangeEvent evt) {//GEN-FIRST:event_xmaxSliderStateChanged
        JSlider slider = (JSlider) evt.getSource();
        int level = slider.getValue() - 2;
        if (graphPainter != null) {
            graphPainter.changeXScale(level);
            frameSlider.setMaximum(frameSlider.getMinimum() + graphPainter.getCurrentOxLen());
            if (frameSlider.getValue() > frameSlider.getMaximum()) {
                frameSlider.setValue(frameSlider.getMaximum());
            }
            frameSlider.revalidate();
            frameSlider.repaint();
        }
    }//GEN-LAST:event_xmaxSliderStateChanged

    private boolean isDel(String content) {
        return "SIL".equals(content);
    }

    private void undoButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_undoButtonActionPerformed
        PhraseInfo lastPhrase = recordedDatabase.removeLastPhrase();
        if (lastPhrase == null) {
            return;
        }
        int start = lastPhrase.getStartFrame();
        int finish = lastPhrase.getFinishFrame();
        String content = lastPhrase.getPhraseContent();
        try {
            graphPainter.moveGraphRight(finish - start + 1);

            startSpinner.setValue(start);
            finishSpinner.setValue(finish);

            String saved = savedPhraseTextArea.getText();
            int index = saved.lastIndexOf("\n");
            if (index >= 0) {
                saved = saved.substring(0, index);
            } else {
                saved = "";
            }
            savedPhraseTextArea.setText(saved);

            if (!isDel(content)) {
                String textContent = currentPhraseTextField.getText() + " " + textContentArea.getText();
                textContentArea.setText(textContent);
                textContentArea.setCaretPosition(0);
                currentPhraseTextField.setText(content);
            }

            if (recordedDatabase.isEmpty()) {
                undoButton.setEnabled(false);
                needToSave = false;
            } else {
                needToSave = true;
            }
        } catch (Exception ex) {
            JOptionPane.showMessageDialog(mainPanel, ex.getMessage());
            ex.printStackTrace();
        }
    }//GEN-LAST:event_undoButtonActionPerformed

    private void saveWaveButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_saveWaveButtonActionPerformed
        JFileChooser fileChooser = new JFileChooser();
        fileChooser.setMultiSelectionEnabled(false);
        FileNameExtensionFilter filter = new FileNameExtensionFilter("Wave files (*.wav)", "wav");
        fileChooser.setFileFilter(filter);

        if (lastDirectory != null) {
            fileChooser.setCurrentDirectory(lastDirectory);
        }

        int ret = fileChooser.showSaveDialog(mainPanel);
        if (ret == JFileChooser.APPROVE_OPTION) {
            lastDirectory = fileChooser.getCurrentDirectory();
            String path = fileChooser.getSelectedFile().getAbsolutePath();
            if (!path.endsWith(".wav")) {
                path = path + ".wav";
            }

            File selectedFile = new File(path);
            try {
                WavFile currentWav = graphPainter.getWavFile();
                int start = frameSlider.getMinimum();
                int finish = frameSlider.getValue();
                int numFrames = finish - start + 1;
                WavFile writeWav = WavFile.newWavFile(selectedFile, currentWav.getNumChannels(), numFrames, currentWav.getValidBits(), currentWav.getSampleRate());
                writeWav.writeFrames(graphPainter.getData(numFrames), numFrames);
                writeWav.close();
            } catch (Exception ex) {
                JOptionPane.showMessageDialog(mainPanel, ex.getMessage());
                ex.printStackTrace();
            }
        }
    }//GEN-LAST:event_saveWaveButtonActionPerformed

    private void audioInfoMenuItemActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_audioInfoMenuItemActionPerformed
        JOptionPane.showMessageDialog(mainPanel, audioInfo);
    }//GEN-LAST:event_audioInfoMenuItemActionPerformed

    private void mergeAllXmlItemActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_mergeAllXmlItemActionPerformed
        JFileChooser fileChooser = new JFileChooser();
        fileChooser.setMultiSelectionEnabled(true);
        FileNameExtensionFilter filter = new FileNameExtensionFilter("XML files (*.xml)", "xml");
        fileChooser.setFileFilter(filter);
        if (lastDirectory != null) {
            fileChooser.setCurrentDirectory(lastDirectory);
        }

        if (fileChooser.showOpenDialog(mainPanel) == JFileChooser.APPROVE_OPTION) {
            try {
                lastDirectory = fileChooser.getCurrentDirectory();
                File[] selectedFiles = fileChooser.getSelectedFiles();
                XmlMerger xmlMerger = new XmlMerger(selectedFiles, lastDirectory.getAbsolutePath());
                String statistic = xmlMerger.start();
                JOptionPane.showMessageDialog(mainPanel, statistic);
            } catch (Exception ex) {
                ex.printStackTrace();
            }
        }
    }//GEN-LAST:event_mergeAllXmlItemActionPerformed
    // Variables declaration - do not modify//GEN-BEGIN:variables
    private javax.swing.JLabel audioFileLabel;
    private javax.swing.JMenuItem audioInfoMenuItem;
    private javax.swing.JLabel currentPhraseLabel;
    private javax.swing.JTextField currentPhraseTextField;
    private javax.swing.JButton delButton;
    private javax.swing.JLabel finishLabel;
    private javax.swing.JSpinner finishSpinner;
    private javax.swing.JSlider frameSlider;
    private javax.swing.JPanel graphPanel;
    private javax.swing.JPanel mainPanel;
    private javax.swing.JMenuBar menuBar;
    private javax.swing.JMenuItem mergeAllXmlItem;
    private javax.swing.JButton minusButton;
    private javax.swing.JMenuItem newMenuItem;
    private javax.swing.JMenuItem openAudioItem;
    private javax.swing.JMenuItem openTextItem;
    private javax.swing.JButton playButton;
    private javax.swing.JButton playRemainButton;
    private javax.swing.JButton plusButton;
    private javax.swing.JButton savePhraseButton;
    private javax.swing.JMenuItem saveResultItem;
    private javax.swing.JButton saveWaveButton;
    private javax.swing.JScrollPane savedPhraseScrollPane;
    private javax.swing.JTextArea savedPhraseTextArea;
    private javax.swing.JLabel startLabel;
    private javax.swing.JSpinner startSpinner;
    private javax.swing.JPanel statusPanel;
    private javax.swing.JTextArea textContentArea;
    private javax.swing.JScrollPane textContentScrollPane;
    private javax.swing.JLabel textFileLabel;
    private javax.swing.JButton undoButton;
    private javax.swing.JMenu viewMenu;
    private javax.swing.JSlider xmaxSlider;
    private javax.swing.JSlider ymaxSlider;
    // End of variables declaration//GEN-END:variables
    private final Timer messageTimer;
    private final Timer busyIconTimer;
    private final Icon idleIcon;
    private final Icon[] busyIcons = new Icon[15];
    private int busyIconIndex = 0;
    private JDialog aboutBox;
    private GraphPainter graphPainter;
    private AudioPlayer player;
    private SelectedPhrase selectedPhrase;
    private int numberCurrentSyllables = 0;
    private RecordedDatabase recordedDatabase;
    private File currentAudioFile;
    private File currentTextFile;
    private boolean needToSave;
    private static final int DEFAULT_LEVEL = 2;
    private File lastDirectory = null;
    private String audioInfo = "";
}
